package com.starview.star.compiler.cafe.compile.cont;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;

import com.starview.platform.data.type.Location;
import com.starview.star.compiler.ErrorReport;
import com.starview.star.compiler.cafe.compile.CafeDictionary;
import com.starview.star.compiler.cafe.compile.CodeContext;
import com.starview.star.compiler.cafe.compile.ISpec;

public class JumpCont implements IContinuation
{
  private final LabelNode jmp;

  public JumpCont(LabelNode lbl)
  {
    this.jmp = lbl;
  }

  @Override
  public boolean isJump()
  {
    return true;
  }

  @Override
  public ISpec cont(ISpec src, CafeDictionary cxt, Location loc, ErrorReport errors, CodeContext ccxt)
  {
    MethodNode mtd = ccxt.getMtd();
    InsnList ins = mtd.instructions;

    if (!isUnconditionalJump(ins.getLast().getOpcode()))
      ins.add(new JumpInsnNode(Opcodes.GOTO, jmp));
    return src;
  }

  public LabelNode getJmp()
  {
    return jmp;
  }

  public static boolean isUnconditionalJump(int opcode)
  {
    switch (opcode) {
    case Opcodes.GOTO:
    case Opcodes.RETURN:
    case Opcodes.RET:
    case Opcodes.ARETURN:
    case Opcodes.LRETURN:
    case Opcodes.FRETURN:
    case Opcodes.DRETURN:
      return true;
    default:
      return false;
    }
  }
}
